var intervals = {};
var target = null;
var wordsSort = {};
var monsterCount = 0;
var score_count = 0;
var score_per_ch = 1;
var score_can_upgrade = 100;
var level = 1;
var speed_min_origin = 400;
var speed_max_origin = 6000;
var speed_min = 500;
var speed_max = 5000;
var is_end = false;
var double_hit = 0; // 连击次数
var max_double_hit = 0;
var is_pause = 0;
var last_word = '';

var i = global_words.length;
var tmpWord;
while (i) {
	i -= 1;
	tmpWord = global_words[i];
    if (!wordsSort[tmpWord[0]]) {
		wordsSort[tmpWord[0]] = [];
	}
	wordsSort[tmpWord[0]].push(tmpWord);
}

// custom exception
function ExceptionFail() {}
function ExceptionSuccess() {}
function ExceptionNoTarget() {}
function ExceptionNotMatch() {}

function getRandInt(min, max) {
  min = Math.ceil(min);
  max = Math.floor(max);
  return Math.floor(Math.random() * (max - min + 1)) + min; //The maximum is inclusive and the minimum is inclusive 
}

function monsterDown(word) {
	var randomSpeed = getRandInt(speed_min, speed_max);
	intervals[word] = set_interval(function(tmpWord) {
		if (is_pause) {
			return;
		}
		try {
			var tmpObj = $('.monster-col[data-word='+tmpWord+']');
			var top = parseInt(tmpObj.css('top'));
			top += 10;
			tmpObj.css('top', top+'px');
			var gameHeight = parseInt($('.game-top').css('height'));
			var selfHeight = parseInt(tmpObj.css('height'));
			if (top > gameHeight-selfHeight) { // 碰到了底部
				hideMonster(tmpWord);
				if (tmpObj.hasClass('monster-living')) {
					throw new ExceptionFail(); // 游戏失败
				}
			}
		} catch (e) {
			handleException(e);
		}
	}, randomSpeed, word);
}

function getRandomWord() {
	var existLetters = {};
	$('.monster-living').each(function(index, el) {
		existLetters[$(el).attr('data-word')[0]] = 1;
	});
	while (true) {
		if (Object.keys(wordsSort).length === 0) {
			alert('Perfect! You have beating all words!')
			throw new ExceptionSuccess();
		}
		var isLower = 1; // 控制出现小写字母开头和大写字母开头出现的概率
		if (1 == getRandInt(1, 10)) {
			isLower = 0; // 让大写字母开头出现的概率为1/10
		}
		var letters = [];
		for (index in wordsSort) {
			if (!existLetters[index]) {
				if (isLower && index == index.toLowerCase()) { // 需要小写开头的字母, 并且该index真的是小写字母
					letters.push(index); // 需要的字母
				}
				if (!isLower && index == index.toUpperCase()){
					letters.push(index); // 需要的字母
				}
			}
		}
		if (!letters.length) {
			continue;
		}

		var letter = letters[getRandInt(0, letters.length - 1)]; // 随机首字母
		if (!wordsSort[letter].length) { // 该组的词用完了!
			delete wordsSort[letter];
			continue;
		}
		var index = getRandInt(0, wordsSort[letter].length - 1); // 随机单词
		var res = wordsSort[letter][index];
		wordsSort[letter].splice(index, 1); // 将该单词删除，保证单词只出现一次!
		return res;
	}
}

function getRandomColor() {
	var colors = [
		// '#e91e63',
		// '#f44336',
		// '#2196f3',
		'#03a9f4',
		// '#00bcd4',
		// '#4caf50',
		// '#8bc34a',
		// '#cddc39',
		// '#ccff00',
		// '#ffeb3b',
	];
	return colors[getRandInt(0, colors.length-1)];
}

function genMonster(monsterNum) {
	try {
		if (!monsterNum) {
			monsterNum = getRandInt(5, 12); // 随机出现的单词数量
		}
		var monsterWord;
		var word_desc;
		var monster;
		var tmp;
		for (var i = 0; i < monsterNum; i++) {
			tmp = getRandomWord();
			monsterWord = tmp.split(' ')[0];
			word_desc = tmp.substring(monsterWord.length+1);
			var offsetStr = '';
			monsterObj = $('\
				<div class="' + offsetStr + 'col-xs-1 monster-col monster-living" data-word="'+monsterWord+'" data-index="'+monsterCount+'">\
					<span class="monster"></span>\
					<div class="word-desc" style="display: none;">'+word_desc+'</div>\
				</div>');
			for (var j = 0; j < monsterWord.length; j++) {
				monster = monsterObj.find('.monster');
				monster.css({
					color: '#9E9E9E',
				});
				monster.attr('data-borderColor', '#4CAF50');
				monster.attr('data-color', '#ffeb3b');
				monster.append('<font class="monster-letter undone ' + monsterWord[j] + '" id="word-'+monsterWord+'-'+j+'">' + monsterWord[j] + '</font>');
			}
			$('.game-top').append(monsterObj);
			monsterCount += 1;
			monsterDown(monsterWord);
		}
	} catch (e) {
		handleException(e);
	}
}

function hideMonster(word) {
	var tmpObj = $('.monster-col[data-word='+word+']');
	// 加入消失效果
	var magics = ['magic', 'puffOut', 'puffOut', 'vanishOut', 'openDownLeftOut', 'openDownRightOut', 'openUpLeftOut', 'openUpRightOut', 'rotateDown', 'rotateUp', 'rotateLeft', 'rotateRight', 'swashOut', 'foolishOut', 'holeOut', 'tinRightOut', 'tinLeftOut', 'tinUpOut', 'tinDownOut', 'bombRightOut', 'bombLeftOut', 'boingOutDown', 'spaceOutUp', 'spaceOutRight', 'spaceOutDown', 'spaceOutLeft'];
	var magic = magics[getRandInt(0, magics.length - 1)];
	tmpObj.addClass('magictime ' + magic);
}

function searchTarget(key) {
	if (target) {
		return target;
	}
	var monsters;
	if (!key) { // 按的是功能键之类的非打印字符键
		throw new ExceptionNoTarget();
	}
	monsters = $('.monster-living[data-word^='+key+']'); // 寻找首字母为key的monster
	if (!monsters.length) {
		throw new ExceptionNoTarget();
	}
	target = $(monsters[0]);
	target.css('z-index', 9999);
	var monster = target.find('.monster');
	monster.css({
		border: 'solid 3px '+monster.attr('data-borderColor'),
	});
	target.find('.word-desc').show();
	// 让下面的发射器也跟着单词的位置移动
	var margetLeft = ((target.attr('data-index') % 12) * (100/12)) + '%';
	$('.game-me').animate({'margin-left': margetLeft}, 1500);	
	last_word = target.attr('data-word')+' '+target.find('.word-desc').text();
}

function handleScore(monster) {
	var word = monster.closest('.monster-col').attr('data-word');
	score_count += score_per_ch * word.length;
	var new_level = Math.ceil(score_count / score_can_upgrade);
	var time;
	if (new_level > level) {
		tips('恭喜您，成功升级为'+new_level+'级💐💐💐！');
		time = get_interval_time(intervals['___init___']) - 10;
		if (time > 1000) {
			change_interval_time(intervals['___init___'],  time);
		}
	}
	level = new_level;
	speed_min = speed_min_origin / level;
	speed_max = speed_max_origin / level;
	$('.info-level').text(level);
	$('.info-score-count').text(score_count);
	$('.info-last-word').text(last_word);
}

function shoot(targetKey) {
	var key = targetKey.text();
	var word = targetKey.closest('.monster-col').attr('data-word');
	var bulletId = 'bullet-' + word + '-' + targetKey.index();
	var targetKeyId = targetKey.attr('id');

	targetKey.removeClass('undone').addClass('done');
	$('.game-top').append('<div class="bullet" data-word="' + word + '" id="' + bulletId + '" data-target-id="' + targetKeyId + '">' + key + '</div>');
	var percent = parseInt($('.game-me').attr('style').replace('margin-left:', ''));
	$('#'+bulletId).css('left', getRandInt(percent-5, percent+10)+'%');
	var offset_end = {
		left: targetKey.closest('.monster-col').position().left + targetKey.position().left + 19.5,
		top: targetKey.closest('.monster-col').position().top + 3,
	}

	if (!target.find('.monster-letter.undone').length) {
		target.removeClass('monster-living').addClass('died');
		target = null
	}
	if (!$('.monster-living').length) {
		throw new ExceptionSuccess();
	}

	var obj = $('#' + $('#'+bulletId).attr('data-target-id'));
	obj.css('color', obj.closest('.monster').attr('data-color'));
	double_hit++;
	if (double_hit > max_double_hit) {
		max_double_hit = double_hit;
	}
	$('.info-double-hit').text(double_hit);
	$('#'+bulletId).animate(offset_end, {
	    duration: 1000,
	    specialEasing: {
	      width: "linear",
	      height: "easeOutBounce"
	    },
	    complete: function() {
	    	var obj = $('#' + $(this).attr('data-target-id'));
	    	$(this).hide();
	    	obj.addClass('colored');
      		var tmpTarget = obj.closest('.monster-col');
      		// 所有字母都消灭后, 停止循环器, 并隐藏单词
      		if (!tmpTarget.find('.monster-letter.undone').length && tmpTarget.find('.monster-letter.done').length == tmpTarget.find('.monster-letter.colored').length) {
      			$('.bullet[data-word=' + tmpTarget.attr('data-word') + ']').hide();
      			obj.closest('.monster').css('border', 'solid 1px #636363');
      			hideMonster(tmpTarget.attr('data-word'))
      			play_audio('success');
      			handleScore(obj.closest('.monster'));
      			clearInterval(intervals[word]);
      		}
	    },
	    step: function(now, fx) { // 让子弹临近目标时隐藏
	    	var obj = $('#' + fx.elem.id);
	    	var tmpTarget = $('#' + obj.attr('data-target-id')).closest('.monster-col');
			if (tmpTarget.position().top >= obj.position().top-20) {
	    		obj.hide();
			}
		}
	});
}

function attackMonster(key) {
	var targetKey;
	if (!target) {
		throw new ExceptionNoTarget();
	}
	targetKey = target.find('.monster-letter.undone:first'); // 找到选定单词中未完成的第一个字母
	if (key != targetKey.text()) {
		throw new ExceptionNotMatch();
	}

	var index;
	if (key >= 'A' && key <= 'Z') {
		index = key.charCodeAt() - 'A'.charCodeAt() + 1;
	} else if (key >= 'a' && key <= 'z') {
		index = key.charCodeAt() - 'a'.charCodeAt() + 27;
	}
	if (index) {
		play_audio(index);
	}
	shoot(targetKey);
}

function see_rule() {
	tips('空格键暂停。消灭屏幕上出现的所有单词即胜利，若单词碰触到最下边，则游戏失败！', 'warning');
}

function tips(msg, type, callback) {
    type = type || 'success';
    $('#my-tips').remove();
    var obj = $('\
        <div  id="my-tips" style="display:none;padding: 0px 20px;position: fixed;top: 0;z-index: 9999;text-align: center;width: 100%;">\
            <div class="alert alert-'+type+' alert-dismissable" style="margin: 0 auto;height: 1vh;font-size: 0.5em;line-height: 1vh; ">\
                 <button type="button" class="close" data-dismiss="alert"\
                        aria-hidden="true">\
                    &times;\
                </button>\
                '+msg+'\
            </div>\
        </div>');
    var delay = 2000;
    if (type == 'danger') {
        delay = 3000;
    } else if (type == 'warning') {
        delay = 4000;
    }
    obj.appendTo('body').slideDown('slow', function() {
        obj.delay(delay).slideUp('slow');
        callback && callback();
    });
}

function handleException(e) {
	if (e instanceof ExceptionNoTarget) {
		// console.log(target)
		// do nothing
	} else if (e instanceof ExceptionNotMatch) {
		double_hit = 0;
		$('.info-double-hit').text(double_hit);
		// console.log(target)
		// do nothing
	} else if (e instanceof ExceptionSuccess) {
		if (is_end) {
			return;
		}
		is_end = true;
		play_audio('success_end');
		tips('恭喜您，游戏挑战成功！最高连击次数为：'+max_double_hit+'🎉🎉🎉🎉🎉🎉');
		clear_all_intervals();
	} else if (e instanceof ExceptionFail) {
		if (is_end) {
			return;
		}
		is_end = true;
		play_audio('fail');
		tips('很遗憾，游戏挑战失败！最高连击次数为：'+max_double_hit+'😭😭😭😭😭😭', 'danger');
		clear_all_intervals();
	}
}

var audio_index = 0;
function num2key(num) {
	var keymap = {
		1: 'C1',
		2: 'D1',
		3: 'E1',
		4: 'F1',
		5: 'G1',
		6: 'A1',
		7: 'B1',
	};
	return keymap[num];
}

function play_audio(file) {
	if (file == 'success' || file == 'success_end' || file == 'fail') {
		return new Audio('mp3/'+file+'.mp3').play();
	}
	// 按一首音乐的顺序放歌~
	var music = '\
		1 1 5 5 6 6 5\
		4 4 3 3 2 2 1\
		5 5 4 4 3 3 2\
		5 5 4 4 3 3 2\
		1 1 5 5 6 6 5\
		4 4 3 3 2 2 1\
	';
	music = music.replace(/\s+/g, ' ').trim();
	music = music.split(' ');
	if (audio_index < music.length) {
		console.log([audio_index,music[audio_index], num2key(music[audio_index])])
		new Audio('piano/'+num2key(music[audio_index])+'.mp3').play();
		audio_index++;
	}
}

$(document).ready(function(){
	genMonster(5);
	// 每隔3秒自动出现1个单词
	intervals['___init___'] = set_interval(function() {
		if (is_pause) {
			return;
		}
		genMonster(1);
	}, 3000);
	$(document).on('keypress', function(e) {
		if (is_end) {
			return;
		}
		try {
			if (e.which == 32) { //空格键
				is_pause = +!is_pause;
				$('.info-tips').html(is_pause ? '暂停' : '&nbsp;');
			}
			if (is_pause) {
				return;
			}
			var key = String.fromCharCode(e.which);
			searchTarget(key);
			attackMonster(key);
		} catch (e) {
			handleException(e);
		}
	});
});
